package com.autoglm.android.core.db

import android.util.Log
import androidx.room.Dao
import androidx.room.Database
import androidx.room.Entity
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.PrimaryKey
import androidx.room.Query
import androidx.room.RoomDatabase
import com.autoglm.android.core.models.AppInfo
import com.autoglm.android.core.models.AppOperation
import com.autoglm.android.core.models.ExecutionStep
import com.autoglm.android.core.models.ScreenInfo
import com.autoglm.android.core.models.UIElement
import com.autoglm.android.core.models.UIElementInfo
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

/**
 * 应用信息数据库实体
 */
@Entity(tableName = "app_info")
data class AppInfoEntity(
    @PrimaryKey val id: String,
    val name: String,
    val packageName: String,
    val operationKnowledge: String,
    val supportLevel: Int, // 0: 未支持, 1: 基础支持, 2: 良好支持, 3: 完全支持
    val lastUpdated: Long
)

/**
 * 屏幕信息数据库实体
 */
@Entity(tableName = "screen_info", primaryKeys = ["id", "appId"])
data class ScreenInfoEntity(
    val id: String,
    val appId: String,
    val name: String,
    val description: String,
    val activityName: String?,
    val screenCapture: String? // Base64编码的屏幕截图
)

/**
 * UI元素信息数据库实体
 */
@Entity(tableName = "element_info", primaryKeys = ["id", "screenId", "appId"])
data class ElementInfoEntity(
    val id: String,
    val screenId: String,
    val appId: String,
    val name: String,
    val type: String,
    val resourceId: String?,
    val className: String?,
    val text: String?,
    val contentDescription: String?,
    val bounds: String?, // JSON格式的矩形区域
    val isClickable: Boolean,
    val isScrollable: Boolean,
    val isLongClickable: Boolean
)

/**
 * 应用信息DAO
 */
@Dao
interface AppInfoDao {
    @Query("SELECT * FROM app_info WHERE name = :name")
    suspend fun getByName(name: String): AppInfoEntity?
    
    @Query("SELECT * FROM app_info WHERE packageName = :packageName")
    suspend fun getByPackageName(packageName: String): AppInfoEntity?
    
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insert(appInfo: AppInfoEntity)
    
    @Query("SELECT * FROM app_info ORDER BY supportLevel DESC LIMIT :limit")
    suspend fun getTopSupportedApps(limit: Int): List<AppInfoEntity>
}

/**
 * 屏幕信息DAO
 */
@Dao
interface ScreenInfoDao {
    @Query("SELECT * FROM screen_info WHERE appId = :appId")
    suspend fun getByAppId(appId: String): List<ScreenInfoEntity>
    
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertAll(screens: List<ScreenInfoEntity>)
}

/**
 * UI元素信息DAO
 */
@Dao
interface ElementInfoDao {
    @Query("SELECT * FROM element_info WHERE appId = :appId")
    suspend fun getByAppId(appId: String): List<ElementInfoEntity>
    
    @Query("SELECT * FROM element_info WHERE screenId = :screenId AND appId = :appId")
    suspend fun getByScreenId(screenId: String, appId: String): List<ElementInfoEntity>
    
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertAll(elements: List<ElementInfoEntity>)
}

/**
 * 应用知识库数据库
 */
@Database(
    entities = [AppInfoEntity::class, ScreenInfoEntity::class, ElementInfoEntity::class],
    version = 1
)
abstract class AppKnowledgeDatabase : RoomDatabase() {
    abstract fun appInfoDao(): AppInfoDao
    abstract fun screenInfoDao(): ScreenInfoDao
    abstract fun elementInfoDao(): ElementInfoDao
}

/**
 * 应用知识库，用于管理应用操作知识
 */
class AppKnowledgeBase(
    private val database: AppKnowledgeDatabase
) {
    companion object {
        private const val TAG = "AppKnowledgeBase"
    }
    
    /**
     * 根据应用名称获取应用信息
     * 
     * @param appName 应用名称
     * @return 应用信息
     */
    suspend fun getAppInfoByName(appName: String): AppInfo = withContext(Dispatchers.IO) {
        Log.d(TAG, "Getting app info for $appName")
        
        try {
            // 查询应用信息
            val appEntity = database.appInfoDao().getByName(appName)
                ?: throw IllegalArgumentException("找不到应用: $appName")
            
            // 查询应用的屏幕信息
            val screenEntities = database.screenInfoDao().getByAppId(appEntity.id)
            val screens = screenEntities.map { screenEntity ->
                // 查询屏幕的UI元素
                val elementEntities = database.elementInfoDao()
                    .getByScreenId(screenEntity.id, appEntity.id)
                    .map { it.toUIElementInfo() }
                
                ScreenInfo(
                    screenName = screenEntity.name,
                    description = screenEntity.description,
                    activityName = screenEntity.activityName,
                    elements = elementEntities
                )
            }
            
            // 查询应用操作知识
            val operationEntities = database.elementInfoDao().getByAppId(appEntity.id)
            val operations = operationEntities.map { it.toUIElementInfo() }
            
            // 组装应用信息
            return@withContext AppInfo(
                appName = appEntity.name,
                packageName = appEntity.packageName,
                commonScreens = screens,
                commonElements = screens.flatMap { it.elements },
                operationKnowledge = screens.joinToString("\n") { it.description }
            )
        } catch (e: Exception) {
            Log.e(TAG, "Error getting app info for $appName", e)
            throw e
        }
    }
    
    /**
     * 根据包名获取应用信息
     * 
     * @param packageName 应用包名
     * @return 应用信息
     */
    suspend fun getAppInfoByPackage(packageName: String): AppInfo = withContext(Dispatchers.IO) {
        Log.d(TAG, "Getting app info for package $packageName")
        
        try {
            // 查询应用信息
            val appEntity = database.appInfoDao().getByPackageName(packageName)
                ?: throw IllegalArgumentException("找不到应用包: $packageName")
            
            // 查询应用的屏幕信息
            val screenEntities = database.screenInfoDao().getByAppId(appEntity.id)
            val screens = screenEntities.map { screenEntity ->
                // 查询屏幕的UI元素
                val elementEntities = database.elementInfoDao()
                    .getByScreenId(screenEntity.id, appEntity.id)
                    .map { it.toUIElementInfo() }
                
                ScreenInfo(
                    screenName = screenEntity.name,
                    description = screenEntity.description,
                    activityName = screenEntity.activityName,
                    elements = elementEntities
                )
            }
            
            // 查询应用操作知识
            val operationEntities = database.elementInfoDao().getByAppId(appEntity.id)
            val operations = operationEntities.map { it.toUIElementInfo() }
            
            // 组装应用信息
            return@withContext AppInfo(
                appName = appEntity.name,
                packageName = appEntity.packageName,
                commonScreens = screens,
                commonElements = screens.flatMap { it.elements },
                operationKnowledge = screens.joinToString("\n") { it.description }
            )
        } catch (e: Exception) {
            Log.e(TAG, "Error getting app info for package $packageName", e)
            throw e
        }
    }
    
    /**
     * 更新应用知识
     * 
     * @param appInfo 应用信息
     */
    suspend fun updateAppInfo(appInfo: AppInfo) = withContext(Dispatchers.IO) {
        Log.d(TAG, "Updating app info for ${appInfo.appName}")
        
        try {
            // 更新或插入应用信息
            var appId = database.appInfoDao().getByName(appInfo.appName)?.id
            
            if (appId == null) {
                // 新应用，插入
                database.appInfoDao().insert(
                    AppInfoEntity(
                        id = appInfo.appName,
                        name = appInfo.appName,
                        packageName = appInfo.packageName,
                        operationKnowledge = appInfo.operationKnowledge,
                        supportLevel = 0,
                        lastUpdated = System.currentTimeMillis()
                    )
                )
            } else {
                // 更新现有应用
                database.appInfoDao().insert(
                    AppInfoEntity(
                        id = appId,
                        name = appInfo.appName,
                        packageName = appInfo.packageName,
                        operationKnowledge = appInfo.operationKnowledge,
                        supportLevel = 0,
                        lastUpdated = System.currentTimeMillis()
                    )
                )
            }
            
            // 处理屏幕信息
            for (screen in appInfo.commonScreens) {
                var screenId = database.screenInfoDao().getByAppId(appId)
                    .find { it.name == screen.screenName }?.id
                
                if (screenId == null) {
                    // 新屏幕，插入
                    database.screenInfoDao().insertAll(
                        listOf(
                            ScreenInfoEntity(
                                id = screen.screenName,
                                appId = appId,
                                name = screen.screenName,
                                description = screen.description,
                                activityName = screen.activityName,
                                screenCapture = null
                            )
                        )
                    )
                } else {
                    // 更新现有屏幕
                    database.screenInfoDao().insertAll(
                        listOf(
                            ScreenInfoEntity(
                                id = screenId,
                                appId = appId,
                                name = screen.screenName,
                                description = screen.description,
                                activityName = screen.activityName,
                                screenCapture = null
                            )
                        )
                    )
                }
                
                // 处理元素信息
                for (element in screen.elements) {
                    val existingElement = database.elementInfoDao()
                        .getByScreenId(screenId, appId)
                        .find { it.name == element.name }
                    
                    if (existingElement == null) {
                        // 新元素，插入
                        database.elementInfoDao().insertAll(
                            listOf(
                                ElementInfoEntity(
                                    id = "${screenId}_${element.name}",
                                    screenId = screenId,
                                    appId = appId,
                                    name = element.name,
                                    type = element.type,
                                    resourceId = element.resourceId,
                                    className = element.className,
                                    text = element.text,
                                    contentDescription = element.contentDescription,
                                    bounds = element.bounds,
                                    isClickable = element.isClickable,
                                    isScrollable = element.isScrollable,
                                    isLongClickable = element.isLongClickable
                                )
                            )
                        )
                    } else {
                        // 更新现有元素
                        database.elementInfoDao().insertAll(
                            listOf(
                                ElementInfoEntity(
                                    id = existingElement.id,
                                    screenId = screenId,
                                    appId = appId,
                                    name = element.name,
                                    type = element.type,
                                    resourceId = element.resourceId,
                                    className = element.className,
                                    text = element.text,
                                    contentDescription = element.contentDescription,
                                    bounds = element.bounds,
                                    isClickable = element.isClickable,
                                    isScrollable = element.isScrollable,
                                    isLongClickable = element.isLongClickable
                                )
                            )
                        )
                    }
                }
            }
            
            // 处理操作知识
            for (operation in appInfo.operationKnowledge) {
                val existingOperation = database.elementInfoDao().getByAppId(appId)
                    .find { it.name == operation.operation }
                
                if (existingOperation == null) {
                    // 新操作，插入
                    database.elementInfoDao().insertAll(
                        listOf(
                            ElementInfoEntity(
                                id = "${appId}_${operation.operation}",
                                screenId = "",
                                appId = appId,
                                name = operation.operation,
                                type = "",
                                resourceId = null,
                                className = null,
                                text = operation.description,
                                contentDescription = null,
                                bounds = null,
                                isClickable = false,
                                isScrollable = false,
                                isLongClickable = false
                            )
                        )
                    )
                } else {
                    // 更新现有操作
                    database.elementInfoDao().insertAll(
                        listOf(
                            ElementInfoEntity(
                                id = existingOperation.id,
                                screenId = "",
                                appId = appId,
                                name = operation.operation,
                                type = "",
                                resourceId = null,
                                className = null,
                                text = operation.description,
                                contentDescription = null,
                                bounds = null,
                                isClickable = false,
                                isScrollable = false,
                                isLongClickable = false
                            )
                        )
                    )
                }
            }
            
            Log.d(TAG, "Successfully updated app info for ${appInfo.appName}")
        } catch (e: Exception) {
            Log.e(TAG, "Error updating app info for ${appInfo.appName}", e)
            throw e
        }
    }
}

/**
 * 扩展函数：转换ScreenInfoEntity到ScreenInfo
 */
private fun ScreenInfoEntity.toScreenInfo(elements: List<UIElementInfo>): ScreenInfo {
    return ScreenInfo(
        screenName = this.name,
        description = this.description,
        activityName = this.activityName,
        elements = elements,
        screenCapture = this.screenCapture
    )
}

/**
 * 扩展函数：转换ElementInfoEntity到UIElementInfo
 */
private fun ElementInfoEntity.toUIElementInfo(): UIElementInfo {
    // 实际项目中需要解析bounds字符串为Rect对象
    return UIElementInfo(
        id = this.id,
        name = this.name,
        type = this.type,
        resourceId = this.resourceId,
        className = this.className,
        text = this.text,
        contentDescription = this.contentDescription,
        bounds = null,  // 需要从JSON字符串解析
        isClickable = this.isClickable,
        isScrollable = this.isScrollable,
        isLongClickable = this.isLongClickable
    )
} 